package com.ruoyi.aimodel.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.ruoyi.aimodel.domain.DeepSeekRequest;
import com.ruoyi.aimodel.domain.DeepSeekResponse;
import com.ruoyi.aimodel.domain.DoubaoRequest;
import com.ruoyi.aimodel.domain.Message;
import com.ruoyi.aimodel.service.EduAiService;
import com.ruoyi.common.redis.service.RedisService;
import io.github.lnyocly.ai4j.service.factor.AiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import org.slf4j.LoggerFactory;

import java.util.*;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import reactor.core.publisher.Mono;

@Service
public class EduAiServiceImpl implements EduAiService {
   @Autowired
    AiService aiService;
    private static final String USER = "user";
    private static final String SYSTEM = "system";
    private static final org.slf4j.Logger log = LoggerFactory.getLogger(EduAiServiceImpl.class);
    private final WebClient webClient;
    private final ObjectMapper objectMapper = new ObjectMapper();
    public EduAiServiceImpl(@Value("${doubao.apiUrl}") String apiUrl,
                               @Value("${doubao.apiKey}") String apiKey) {
        log.info(apiUrl);
        log.info(apiKey);
        this.webClient = WebClient.builder()
                .baseUrl(apiUrl)
                .defaultHeader("Authorization", "Bearer " + apiKey)
                .build();
    }
    @Autowired
    private RedisService redisService;
    // 设置默认缓存时间为30分钟
    @Value("${youDeepseek.cache.expiration.minutes:30}")
    private int cacheExpirationMinutes;

    @Override
    public Flux<String> getDoubaoStream(String userid, String content) {
        return callDoubaoStream(userid,content);
    }

    @Override
    public String getDoubaoChat(String userid, String msg) {
        Mono<String> stringMono = getDoubaoChatAsync(userid, msg);
        log.info(new StringBuilder().append("接收返回：").append(stringMono).toString());
        return stringMono.block();
    }


    public Flux<String> callDoubaoStream(String userId,String userMessage) {
        String chatKey = getChatKey(userId);

        // 获取或初始化用户的对话历史
        Object object = redisService.getCacheMapValue(chatKey, String.valueOf(userId));


        List<Message> messages = Objects.isNull(object) ? new ArrayList<>() : (List<Message>) object;
        messages.add(new Message("user", userMessage));
        for (Message message : messages) {
           log.info("Role: " + message.getRole() + ", Content: " + message.getContent());
        }        // 构建请求体
        DoubaoRequest request = new DoubaoRequest("doubao-1.5-pro-32k-250115", messages, true);
        // 用于累积回答片段
        StringBuffer accumulatedContent = new StringBuffer();

        // 发送异步请求
        return webClient.post()
                .bodyValue(request)
                .retrieve()
                .bodyToFlux(String.class)
                .flatMap(chunk -> {
                    log.info("接收部分: " + chunk);
                    if ("[DONE]".equals(chunk.trim())) {
                        return Flux.empty();
                    }
                    try {
                        JsonNode rootNode = objectMapper.readTree(chunk);
                        JsonNode choicesNode = rootNode.path("choices");
                        if (choicesNode.isArray() && !choicesNode.isEmpty()) {
                            JsonNode deltaNode = choicesNode.get(0).path("delta");
                            String content = deltaNode.path("content").asText("");
                            if (!content.isEmpty()) {
                                // 累积回答片段
                                // 累积回答片段
                                accumulatedContent.append(content);
                                return Flux.just(content);
                            }
                        } else {
                            log.error("Choices 不能为空.");
                        }
                    } catch (Exception e) {
                        log.error("Failed to parse DeepSeek API response: " + e.getMessage());
                        return Flux.error(new RuntimeException("Failed to parse DeepSeek API response: " + e.getMessage()));
                    }
                    // 忽略非数据行
                    return Flux.empty();
                })
                .onErrorResume(e -> {
                    log.error("Failed to call DeepSeek API: " + e.getMessage());
                    return Flux.error(new RuntimeException("Failed to call DeepSeek API: " + e.getMessage()));
                })
                .doOnComplete(() -> {
// 确保在流式输出完成后保存完整的对话历史到 Redis
                    if (accumulatedContent.length() > 0) {
                        messages.add(new Message(SYSTEM, accumulatedContent.toString()));
                        redisService.setCacheMapValue(chatKey, String.valueOf(userId),messages);
                        redisService.expire(chatKey, cacheExpirationMinutes);

                    }
                });
    }

    /**
     *  异步调用doubao API
     *
     * @param userId
     * @param userMessage
     * @return {@link Mono }<{@link String }>
     */
    public Mono<String> getDoubaoChatAsync(String userId, String userMessage) {
        String chatKey = getChatKey(userId);

        // 获取或初始化用户的对话历史
        Object object = redisService.getCacheMapValue(chatKey, String.valueOf(userId));
        List<Message> messages = Objects.isNull(object) ? new ArrayList<>() : (List<Message>) object;
        // 添加新的用户消息到对话历史
        messages.add(new Message("user", userMessage));
        for (Message message : messages) {
            log.info("Role: " + message.getRole() + ", Content: " + message.getContent());
        }

        // 构建请求体
        DoubaoRequest request = new DoubaoRequest("doubao-1.5-pro-32k-250115", messages, false);


        // 发送异步请求
        return webClient.post()
                .bodyValue(request)
                .retrieve()
                .bodyToMono(DeepSeekResponse.class)
                .map(response -> {
                    if (response.getChoices() != null && !response.getChoices().isEmpty()) {
                        String content = response.getChoices().get(0).getMessage().getContent();
                        messages.add(new Message(SYSTEM, content));
                        redisService.setCacheMapValue(chatKey, String.valueOf(userId), messages);
                        redisService.expire(chatKey, cacheExpirationMinutes);
                        log.info("content："+content);
                        return content;
                    } else {
                        throw new RuntimeException("Failed to call 豆包 API: No choices in response");
                    }
                })
                .onErrorResume(e -> Mono.error(new RuntimeException("Failed to call 豆包 API: " + e.getMessage())));
    }
    private String getChatKey(String userId) {
        return EduAiServiceImpl.CacheConstant.DEEP_SEEK_CHAT_KEY + userId;
    }
    private static class CacheConstant {
        public static final String DEEP_SEEK_CHAT_KEY = "doubao_chat_";
    }



}
